package com.frank.loadinglibrary.common.element;

import com.frank.loadinglibrary.base.baseanimations.BaseAnimationController;
import com.frank.loadinglibrary.base.baseelement.BaseElement;
import com.frank.loadinglibrary.base.baseelement.IComponentCallback;
import com.frank.loadinglibrary.utils.SimpleAnimatorListener;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import java.util.ArrayList;

/**
 * @author SUQI
 * @date 2021/6/2
 * @description
 **/
public class CubeGridElement extends BaseElement implements BaseAnimationController.IAnimationController<AnimatorValue> {

    private final float valueZeroPointFive = 0.5f;
    private final float valueZeroPointTwoFive = 0.25f;
    private int num = 9;
    private float[] radius = new float[num];
    private int[] delays = new int[]{
            200, 100, 0,
            300, 200, 100,
            400, 300, 200
    };
    private Paint mPaint;
    private Color color;

    private CubeGridElement(IComponentCallback callback) {
        this.callback = callback;
    }

    @Override
    public ArrayList<AnimatorValue> onCreateAnimators() {
        ArrayList<AnimatorValue> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            TimingAnimatorValue animatorValue = new TimingAnimatorValue();
            animatorValue.setLoopedCount(Animator.INFINITE);
            animatorValue.setDelay(delays[i]);
            animatorValue.setDuration(25);
            int finalI = i;
            animatorValue.setStateChangedListener(new SimpleAnimatorListener() {
                @Override
                public void onStart(Animator animator) {
                    stepIncrease(animatorValue, finalI);
                }
            });
            animatorValue.setLoopedListener(animator -> stepIncrease(animatorValue, finalI));
            list.add(animatorValue);
        }
        return list;
    }

    private void stepIncrease(TimingAnimatorValue animatorValue, int finalI) {
        if (animatorValue.step > 1) {
            animatorValue.step = 0;
        }
        float v = animatorValue.step;
        boolean isInQuaToHalf = v >= valueZeroPointTwoFive && v <= valueZeroPointFive;
        if (v < valueZeroPointTwoFive) {
            v = 1 - (v * 4);
        } else if (isInQuaToHalf) {
            v = (v - 0.25f) * 4;
        } else {
            v = 1f;
        }
        radius[finalI] = v;
        callback.reflushComponent();
        animatorValue.step += 0.019;
    }

    @Override
    public void onAnimationReset() {
        //do nothing because donot need to reset animation params
    }

    @Override
    public BaseAnimationController.IAnimationController<AnimatorValue> initAnimationController() {
        return this;
    }

    @Override
    public void initPaint() {
        super.initPaint();
        mPaint = new Paint();
        mPaint.setColor(color);
        mPaint.setAntiAlias(true);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        RectFloat bounds = clipSquare(getRect(), 50);
        int width = (int) (bounds.getWidth() * 0.33f);
        int height = (int) (bounds.getHeight() * 0.33f);
        for (int i = 0; i < num; i++) {
            int x = i % 3;
            int y = i / 3;
            float l = bounds.left + x * width;
            float t = bounds.top + y * height;
            RectFloat max = new RectFloat(l, t, l + width, t + width);
            float r = max.getWidth() / 2f * radius[i];

            RectFloat now = new RectFloat(
                    max.getVerticalCenter() - r,
                    max.getHorizontalCenter() - r,
                    max.getVerticalCenter() + r,
                    max.getHorizontalCenter() + r
            );

            canvas.drawRect(now, mPaint);
        }
    }

    private RectFloat getRect() {
        return new RectFloat(0, 0, mWidth, mHeight);
    }

    public RectFloat clipSquare(RectFloat rect, int bound) {
        float w = rect.getWidth();
        float h = rect.getHeight();
        float min = Math.min(w, h);
        float cx = rect.getCenter().getPointX();
        float cy = rect.getCenter().getPointY();
        float r = min / 2;
        return new RectFloat(
                cx - r + bound,
                cy - r + bound,
                cx + r - bound,
                cy + r - bound
        );
    }

    private void apply(CubeGridBuilder builder) {
        this.color = builder.color == null ? Color.WHITE : builder.color;
        initPaint();
    }

    public static class TimingAnimatorValue extends AnimatorValue {
        public float step = 0;

        public TimingAnimatorValue() {
            //do nothing
        }
    }

    public static class CubeGridBuilder {
        private IComponentCallback iComponentCallback;
        private Color color;

        public CubeGridBuilder(IComponentCallback iComponentCallback) {
            this.iComponentCallback = iComponentCallback;
        }

        public CubeGridBuilder setColor(Color color) {
            this.color = color;
            return this;
        }

        public CubeGridElement build() {
            CubeGridElement cubeGridElement = new CubeGridElement(iComponentCallback);
            cubeGridElement.apply(this);
            return cubeGridElement;
        }
    }
}
